#include "ce_core.h"

static ce_atomic_t wgid = 0;

void
ce_waitgroup_init(ce_waitgroup_t *wg) {
    wg->count = 0;

    pid_t pid = getpid();
    ce_atomic_t id = ce_atomic_fetch_add(&wgid, 1);
    snprintf(wg->name, sizeof(wg->name), "%08x.%016lx", pid, id);

    sem_unlink(wg->name);
    wg->sem = sem_open(wg->name, O_CREAT|O_EXCL, 0600, 0);
}

void
ce_waitgroup_destroy(ce_waitgroup_t *wg) {
    sem_close(wg->sem);
    sem_unlink(wg->name);
}

void
ce_waitgroup_add(ce_waitgroup_t *wg) {
    ce_atomic_fetch_add(&wg->count, 1);
}

void
ce_waitgroup_done(ce_waitgroup_t *wg) {
    ce_atomic_fetch_add(&wg->count, -1);

    if (wg->count <= 0) {
        sem_post(wg->sem);
    }
}

void
ce_waitgroup_wait(ce_waitgroup_t *wg) {
    for (;;) {
        if (wg->count <= 0) {
            return;
        }

        sem_wait(wg->sem);
    }
}
